home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / C / readfuncs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-21  |  49.2 KB  |  2,169 lines

  1. /*
  2.  *  READFUNCS.C -- Reader functions for Postgres tree nodes.
  3.  *
  4.  *    These routines read in and allocate space for plans.
  5.  *    The main function is at the bottom and figures out what particular
  6.  *      function to use.
  7.  *
  8.  *      All these functions assume that lsptok already has its string.
  9.  *
  10.  *    XXX many of these functions have never been tested because
  11.  *        the nodes they support never appear in plans..  also there
  12.  *        are some nodes which greg needs to finish (they are missing
  13.  *        or incomplete).  -cim 5/31/90
  14.  */
  15.  
  16.  
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <strings.h>
  20. #ifdef linux
  21. double atof(const char *);
  22. #endif
  23.  
  24. #include "tmp/postgres.h"
  25.  
  26. RcsId("$Header: /private/postgres/src/lib/C/RCS/readfuncs.c,v 1.44 1992/07/26 17:07:05 mer Exp $");
  27.  
  28. #include "access/heapam.h"
  29. #include "access/htup.h"
  30. #include "utils/fmgr.h"
  31. #include "utils/log.h"
  32.  
  33. #include "catalog/syscache.h"
  34. #include "catalog/pg_type.h"
  35.  
  36. #include "tags.h"
  37.  
  38. #include "nodes/pg_lisp.h"
  39. #include "nodes/nodes.h"
  40. #include "nodes/primnodes.h"
  41. #include "nodes/primnodes.a.h"
  42. #include "nodes/plannodes.h"
  43. #include "nodes/execnodes.h"
  44. #include "nodes/execnodes.a.h"
  45. #include "nodes/relation.h"
  46.  
  47. extern LispValue lispRead();
  48. extern char *lsptok ARGS((char *string, int *length));
  49. extern Datum readValue();
  50.  
  51. /* ----------------
  52.  *    node creator declarations
  53.  * ----------------
  54.  */
  55. extern Agg        RMakeAgg();
  56. extern Append         RMakeAppend();
  57. extern CInfo         RMakeCInfo();
  58. extern Const         RMakeConst();
  59. extern EState         RMakeEState();
  60. extern Existential     RMakeExistential();
  61. extern Expr         RMakeExpr();
  62. extern Func         RMakeFunc();
  63. extern HInfo         RMakeHInfo();
  64. extern Hash         RMakeHash();
  65. extern HashJoin     RMakeHashJoin();
  66. extern HashPath     RMakeHashPath();
  67. extern IndexPath     RMakeIndexPath();
  68. extern IndexScan     RMakeIndexScan();
  69. extern JInfo         RMakeJInfo();
  70. extern Join         RMakeJoin();
  71. extern JoinKey         RMakeJoinKey();
  72. extern JoinMethod     RMakeJoinMethod();
  73. extern JoinPath     RMakeJoinPath();
  74. extern JoinRuleInfo    RMakeJoinRuleInfo();
  75. extern MergeJoin     RMakeMergeJoin();
  76. extern MergeOrder     RMakeMergeOrder();
  77. extern MergePath     RMakeMergePath();
  78. extern NestLoop     RMakeNestLoop();
  79. extern Oper         RMakeOper();
  80. extern OrderKey     RMakeOrderKey();
  81. extern Param         RMakeParam();
  82. extern Path         RMakePath();
  83. extern Plan         RMakePlan();
  84. extern Rel         RMakeRel();
  85. extern Result         RMakeResult();
  86. extern Resdom         RMakeResdom();
  87. extern Scan         RMakeScan();
  88. extern SeqScan         RMakeSeqScan();
  89. extern Sort         RMakeSort();
  90. extern SortKey         RMakeSortKey();
  91. extern Temp         RMakeTemp();
  92. extern Unique        RMakeUnique();
  93. extern Var         RMakeVar();
  94. extern Array         RMakeArray();
  95. extern ArrayRef        RMakeArrayRef();
  96.  
  97. /* ----------------
  98.  *    _getPlan
  99.  * ----------------
  100.  */
  101. void
  102. _getPlan(node)
  103.     Plan node;
  104. {
  105.     char *token;
  106.     int length;
  107.  
  108.     token = lsptok(NULL, &length);        /* first token is :cost */
  109.     token = lsptok(NULL, &length);        /* next is the actual cost */
  110.  
  111.     node->cost = (Cost) atof(token);
  112.  
  113.     token = lsptok(NULL, &length);        /* skip the :size */
  114.     token = lsptok(NULL, &length);        /* get the plan_size */
  115.     node->plan_size = (Count) atoi(token);
  116.  
  117.     token = lsptok(NULL, &length);        /* skip the :width */
  118.     token = lsptok(NULL, &length);        /* get the plan_width */
  119.     node->plan_width = (Count) atoi(token);
  120.  
  121.     token = lsptok(NULL, &length);        /* eat the :fragment stuff */
  122.     token = lsptok(NULL, &length);          /* get the fragment */
  123.     node->fragment = (Count) atoi(token);
  124.  
  125.     token = lsptok(NULL, &length);        /* eat the :parallel stuff */
  126.     token = lsptok(NULL, &length);          /* get the parallel */
  127.     node->parallel = (Count) atoi(token);
  128.  
  129.     token = lsptok(NULL, &length);        /* eat the :state stuff */
  130.     token = lsptok(NULL, &length);        /* now get the state */ 
  131.  
  132.     if (!strncmp(token, "nil", 3))
  133.     {
  134.         node->state = (struct EState *) NULL;
  135.     } 
  136.     else /* Disgusting hack until I figure out what to do here */
  137.     {
  138.         node->state = (struct EState *) ! NULL;
  139.     }
  140.  
  141.     token = lsptok(NULL, &length);        /* eat :qptargetlist */
  142.  
  143.     node->qptargetlist = lispRead(true);
  144.  
  145.     token = lsptok(NULL, &length);        /* eat :qpqual */
  146.  
  147.     node->qpqual = lispRead(true);
  148.  
  149.     token = lsptok(NULL, &length);        /* eat :lefttree */
  150.  
  151.     node->lefttree = (struct Plan *) lispRead(true);
  152.  
  153.     token = lsptok(NULL, &length);        /* eat :righttree */
  154.  
  155.     node->righttree = (struct Plan *) lispRead(true);
  156.  
  157. }
  158.  
  159. /*
  160.  *  Stuff from plannodes.h
  161.  */
  162.  
  163. /* ----------------
  164.  *    _readPlan
  165.  * ----------------
  166.  */
  167. Plan
  168. _readPlan()
  169. {
  170.     char *token;
  171.     int length;
  172.     Plan local_node;
  173.  
  174.     local_node = RMakePlan();
  175.     
  176.     _getPlan(local_node);
  177.     
  178.     return( local_node );
  179. }
  180.  
  181. /* ----------------
  182.  *    _readResult
  183.  *
  184.  *     Does some obscene, possibly unportable, magic with
  185.  *    sizes of things.
  186.  * ----------------
  187.  */
  188. Result
  189. _readResult()
  190. {
  191.     Result    local_node;
  192.     char *token;
  193.     int length;
  194.  
  195.     local_node = RMakeResult();
  196.     
  197.     _getPlan(local_node);
  198.  
  199.     token = lsptok(NULL, &length);        /* eat :resrellevelqual */
  200.  
  201.     local_node->resrellevelqual = lispRead(true);  /* now read it */
  202.  
  203.     token = lsptok(NULL, &length);        /* eat :resconstantqual */
  204.  
  205.     local_node->resconstantqual = lispRead(true);    /* now read it */
  206.  
  207.     return( local_node );
  208. }
  209.  
  210. /* ----------------
  211.  *    _readExistential
  212.  *
  213.  *    Existential nodes are only used by the planner.
  214.  * ----------------
  215.  */
  216.  
  217. Existential
  218. _readExistential()
  219. {
  220.     Existential    local_node;
  221.  
  222.     local_node = RMakeExistential();
  223.  
  224.     _getPlan(local_node);
  225.     
  226.     return( local_node );
  227. }
  228.  
  229. /* ----------------
  230.  *    _readAppend
  231.  *
  232.  *  Append is a subclass of Plan.
  233.  * ----------------
  234.  */
  235.  
  236. Append
  237. _readAppend()
  238. {
  239.     Append local_node;
  240.     char *token;
  241.     int length;
  242.  
  243.     local_node = RMakeAppend();
  244.  
  245.     _getPlan(local_node);
  246.  
  247.     token = lsptok(NULL, &length);            /* eat :unionplans */
  248.  
  249.     local_node->unionplans = lispRead(true);     /* now read it */
  250.     
  251.     token = lsptok(NULL, &length);            /* eat :unionrelid */
  252.     token = lsptok(NULL, &length);            /* get unionrelid */
  253.  
  254.     local_node->unionrelid = atoi(token);
  255.  
  256.     token = lsptok(NULL, &length);        /* eat :unionrtentries */
  257.  
  258.     local_node->unionrtentries = lispRead(true);    /* now read it */
  259.  
  260.     return(local_node);
  261. }
  262.  
  263. /* ----------------
  264.  *     _readJoinRuleInfo
  265.  *
  266.  * ----------------
  267.  */
  268. JoinRuleInfo
  269. _readJoinRuleInfo()
  270. {
  271.     JoinRuleInfo    local_node;
  272.     char *token;
  273.     int length;
  274.  
  275.     local_node = RMakeJoinRuleInfo();
  276.  
  277.     token = lsptok(NULL, &length);            /* eat :operator */
  278.     token = lsptok(NULL, &length);            /* get operator */
  279.     
  280.     local_node->jri_operator = atol(token);
  281.  
  282.     token = lsptok(NULL, &length);            /* eat :inattrno */
  283.     token = lsptok(NULL, &length);            /* get inattrno */
  284.     
  285.     local_node->jri_inattrno = atoi(token);
  286.  
  287.     token = lsptok(NULL, &length);            /* eat :outattrno */
  288.     token = lsptok(NULL, &length);            /* get outattrno */
  289.     
  290.     local_node->jri_outattrno = atoi(token);
  291.  
  292.     /*
  293.      * a rule lock is printed as a string enclosed in double
  294.      * quotes. So, we first read the string and then
  295.      * call `StringToRuleLock()' to get the actual RuleLock
  296.      * structure.
  297.      */
  298.     token = lsptok(NULL, &length);            /* eat :lock */
  299.     token = lsptok(NULL, &length);            /* get lock */
  300.     /*
  301.      * peel off the double quotes...
  302.      */
  303.     token++;
  304.     token[length - 2] = '\0';
  305.     local_node->jri_lock = StringToRuleLock(token);
  306.     token[length - 2] = '\"';
  307.  
  308.     token = lsptok(NULL, &length);            /* eat :ruleid */
  309.     token = lsptok(NULL, &length);            /* get ruleId */
  310.     
  311.     local_node->jri_ruleid = atol(token);
  312.  
  313.     token = lsptok(NULL, &length);            /* eat :stubid */
  314.     token = lsptok(NULL, &length);            /* get stubid */
  315.     
  316.     local_node->jri_stubid = atoi(token);
  317.  
  318.     /*
  319.      * remember: JoinRuleInfo->stub is only temporarily used.
  320.      * so its actual value is of no interest.
  321.      * Always initialize it to NULL
  322.      */
  323.     token = lsptok(NULL, &length);            /* eat :stub */
  324.     token = lsptok(NULL, &length);            /* skip stub */
  325.     local_node->jri_stub = (Prs2OneStub) NULL;
  326.  
  327.     return(local_node);
  328. }
  329.  
  330. /* ----------------
  331.  *    _getJoin
  332.  *
  333.  * In case Join is not the same structure as Plan someday.
  334.  * ----------------
  335.  */
  336. void
  337. _getJoin(node)
  338.     Join node;
  339. {
  340.     char        *token;
  341.     int length;
  342.  
  343.     _getPlan(node);
  344.  
  345.     token = lsptok(NULL, &length);    /* skip ruleinfo: */
  346.     node->ruleinfo = (struct JoinRuleInfo *) lispRead(true);
  347.  
  348. }
  349.  
  350.  
  351. /* ----------------
  352.  *    _readJoin
  353.  *
  354.  *  Join is a subclass of Plan
  355.  * ----------------
  356.  */
  357. Join
  358. _readJoin()
  359. {
  360.     Join    local_node;
  361.  
  362.     local_node = RMakeJoin();
  363.  
  364.     _getJoin(local_node);
  365.     
  366.     return( local_node );
  367. }
  368.  
  369. /* ----------------
  370.  *    _readNestLoop
  371.  *    
  372.  *  NestLoop is a subclass of Join
  373.  * ----------------
  374.  */
  375.  
  376. NestLoop
  377. _readNestLoop()
  378. {
  379.     NestLoop    local_node;
  380.  
  381.     local_node = RMakeNestLoop();
  382.  
  383.     _getJoin(local_node);
  384.     
  385.     return( local_node );
  386. }
  387.  
  388. /* ----------------
  389.  *    _readMergeJoin
  390.  *    
  391.  *  MergeJoin is a subclass of Join
  392.  * ----------------
  393.  */
  394.  
  395. MergeJoin
  396. _readMergeJoin()
  397. {
  398.     MergeJoin    local_node;
  399.     char        *token;
  400.     int length;
  401.  
  402.     local_node = RMakeMergeJoin();
  403.  
  404.     _getJoin(local_node);
  405.     token = lsptok(NULL, &length);            /* eat :mergeclauses */
  406.     
  407.     local_node->mergeclauses = lispRead(true);    /* now read it */
  408.  
  409.     token = lsptok(NULL, &length);            /* eat :mergesortop */
  410.  
  411.     token = lsptok(NULL, &length);            /* get mergesortop */
  412.  
  413.     local_node->mergesortop = atol(token);
  414.  
  415.     return( local_node );
  416. }
  417.  
  418. /* ----------------
  419.  *    _readHashJoin
  420.  *    
  421.  *  HashJoin is a subclass of Join.
  422.  * ----------------
  423.  */
  424.  
  425. HashJoin
  426. _readHashJoin()
  427. {
  428.     HashJoin    local_node;
  429.     char         *token;
  430.     int length;
  431.  
  432.     local_node = RMakeHashJoin();
  433.  
  434.     _getJoin(local_node);
  435.  
  436.     token = lsptok(NULL, &length);            /* eat :hashclauses */
  437.     local_node->hashclauses = lispRead(true);    /* now read it */
  438.  
  439.     token = lsptok(NULL, &length);            /* eat :hashjoinop */
  440.     token = lsptok(NULL, &length);            /* get hashjoinop */
  441.     local_node->hashjoinop = atoi(token);
  442.  
  443.     token = lsptok(NULL, &length);        /* eat :hashjointable */
  444.     token = lsptok(NULL, &length);        /* eat hashjointable */
  445.     local_node->hashjointable = NULL;
  446.     
  447.     token = lsptok(NULL, &length);        /* eat :hashjointablekey */
  448.     token = lsptok(NULL, &length);        /* eat hashjointablekey */
  449.     local_node->hashjointablekey = 0;
  450.     
  451.     token = lsptok(NULL, &length);        /* eat :hashjointablesize */
  452.     token = lsptok(NULL, &length);        /* eat hashjointablesize */
  453.     local_node->hashjointablesize = 0;
  454.     
  455.     token = lsptok(NULL, &length);        /* eat :hashdone */
  456.     token = lsptok(NULL, &length);        /* eat hashdone */
  457.     local_node->hashdone = false;
  458.     
  459.     return( local_node );
  460. }
  461.  
  462. /* ----------------
  463.  *    _getScan
  464.  *
  465.  *  Scan is a subclass of Node
  466.  *  (Actually, according to the plannodes.h include file, it is a
  467.  *  subclass of Plan.  This is why _getPlan is used here.)
  468.  *
  469.  *  Scan gets its own get function since stuff inherits it.
  470.  * ----------------
  471.  */
  472. void
  473. _getScan(node)
  474.     Scan node;
  475. {
  476.     char *token;
  477.     int length;
  478.  
  479.     _getPlan(node);
  480.     
  481.     token = lsptok(NULL, &length);            /* eat :scanrelid */
  482.  
  483.     token = lsptok(NULL, &length);            /* get scanrelid */
  484.  
  485.     node->scanrelid = atoi(token);
  486. }
  487.  
  488. /* ----------------
  489.  *    _readScan
  490.  *    
  491.  * Scan is a subclass of Plan (Not Node, see above).
  492.  * ----------------
  493.  */
  494. Scan
  495. _readScan()
  496. {
  497.     Scan     local_node;
  498.  
  499.     local_node = RMakeScan();
  500.  
  501.     _getScan(local_node);
  502.  
  503.     return(local_node);
  504. }
  505.  
  506. /* ----------------
  507.  *    _readSeqScan
  508.  *    
  509.  *  SeqScan is a subclass of Scan
  510.  * ----------------
  511.  */
  512. SeqScan
  513. _readSeqScan()
  514. {
  515.     SeqScan     local_node;
  516.  
  517.     local_node = RMakeSeqScan();
  518.  
  519.     _getScan(local_node);
  520.  
  521.     return(local_node);
  522. }
  523.  
  524. /* ----------------
  525.  *    _readIndexScan
  526.  *    
  527.  *  IndexScan is a subclass of Scan
  528.  * ----------------
  529.  */
  530. IndexScan
  531. _readIndexScan()
  532. {
  533.     IndexScan    local_node;
  534.     char        *token;
  535.     int length;
  536.  
  537.     local_node = RMakeIndexScan();
  538.  
  539.     _getScan(local_node);
  540.  
  541.     token = lsptok(NULL, &length);            /* eat :indxid */
  542.  
  543.     local_node->indxid = lispRead(true);        /* now read it */
  544.     
  545.     token = lsptok(NULL, &length);            /* eat :indxqual */
  546.  
  547.     local_node->indxqual = lispRead(true);         /* now read it */
  548.  
  549.     return(local_node);
  550. }
  551.  
  552. /* ----------------
  553.  *    _readTemp
  554.  *    
  555.  *  Temp is a subclass of Plan
  556.  * ----------------
  557.  */
  558. Temp
  559. _readTemp()
  560. {
  561.     Temp        local_node;
  562.     char        *token;
  563.     int length;
  564.  
  565.     local_node = RMakeTemp();
  566.  
  567.     _getPlan(local_node);
  568.  
  569.     token = lsptok(NULL, &length);            /* eat :tempid */
  570.     token = lsptok(NULL, &length);            /* get tempid */
  571.  
  572.     local_node->tempid = atol(token);
  573.  
  574.     token = lsptok(NULL, &length);            /* eat :keycount */
  575.  
  576.     token = lsptok(NULL, &length);            /* get keycount */
  577.  
  578.     local_node->keycount = atoi(token);
  579.  
  580.     return(local_node);
  581. }
  582.  
  583. /* ----------------
  584.  *    _readSort
  585.  *    
  586.  *  Sort is a subclass of Temp
  587.  * ----------------
  588.  */
  589. Sort
  590. _readSort()
  591. {
  592.     Sort        local_node;
  593.     char        *token;
  594.     int length;
  595.  
  596.     local_node = RMakeSort();
  597.  
  598.     _getPlan(local_node);
  599.  
  600.     token = lsptok(NULL, &length);            /* eat :tempid */
  601.     token = lsptok(NULL, &length);            /* get tempid */
  602.  
  603.     local_node->tempid = atol(token);
  604.  
  605.     token = lsptok(NULL, &length);            /* eat :keycount */
  606.  
  607.     token = lsptok(NULL, &length);            /* get keycount */
  608.  
  609.     local_node->keycount = atoi(token);
  610.  
  611.     return(local_node);
  612. }
  613.  
  614. Agg
  615. _readAgg()
  616. {
  617.     Agg             local_node;
  618.     char            *token;
  619.     int length;
  620.  
  621.     local_node = RMakeAgg();
  622.     _getPlan(local_node);
  623.  
  624.     token = lsptok(NULL, &length);                  /* eat :tempid */
  625.     token = lsptok(NULL, &length);                  /* get tempid */
  626.  
  627.     local_node->tempid = atol(token);
  628.  
  629.     token = lsptok(NULL, &length);                  /* eat :keycount */
  630.     token = lsptok(NULL, &length);                  /* get keycount */
  631.  
  632.     local_node->tempid = atoi(token);
  633.  
  634.     return(local_node);
  635. }
  636.  
  637. /* ----------------
  638.  *    _readUnique
  639.  *
  640.  * For some reason, unique is a subclass of Temp.
  641.  */
  642. Unique
  643. _readUnique()
  644. {
  645.     Unique        local_node;
  646.     char        *token;
  647.     int        length;
  648.  
  649.     local_node = RMakeUnique();
  650.  
  651.     _getPlan(local_node);
  652.  
  653.     token = lsptok(NULL, &length);            /* eat :tempid */
  654.     token = lsptok(NULL, &length);            /* get :tempid */
  655.     local_node->tempid = atol(token);
  656.  
  657.     token = lsptok(NULL, &length);            /* eat :keycount */
  658.     token = lsptok(NULL, &length);            /* get :keycount */
  659.     local_node->keycount = atoi(token);
  660.  
  661.     return(local_node);
  662. }
  663.  
  664. /* ----------------
  665.  *    _readHash
  666.  *    
  667.  *  Hash is a subclass of Temp
  668.  * ----------------
  669.  */
  670. Hash
  671. _readHash()
  672. {
  673.     Hash        local_node;
  674.     char        *token;
  675.     int length;
  676.  
  677.     local_node = RMakeHash();
  678.  
  679.     _getPlan(local_node);
  680.  
  681.     token = lsptok(NULL, &length);            /* eat :hashkey */
  682.     local_node->hashkey = (Var) lispRead(true);
  683.  
  684.     token = lsptok(NULL, &length);        /* eat :hashtable */
  685.     token = lsptok(NULL, &length);        /* eat hashtable address*/
  686.     local_node->hashtable = NULL;
  687.  
  688.     token = lsptok(NULL, &length);        /* eat :hashtablekey*/
  689.     token = lsptok(NULL, &length);        /* get hashtablekey */
  690.     local_node->hashtablekey = 0;
  691.  
  692.     token = lsptok(NULL, &length);        /* eat :hashtablesize*/
  693.     token = lsptok(NULL, &length);        /* get hashtablesize */
  694.     local_node->hashtablesize = 0;
  695.  
  696.     return(local_node);
  697. }
  698.  
  699. /*
  700.  *  Stuff from primnodes.h.
  701.  */
  702.  
  703. /* ----------------
  704.  *    _readResdom
  705.  *    
  706.  *  Resdom is a subclass of Node
  707.  * ----------------
  708.  */
  709. Resdom
  710. _readResdom()
  711. {
  712.     Resdom        local_node;
  713.     char        *token;
  714.     int length;
  715.  
  716.     local_node = RMakeResdom();
  717.  
  718.     token = lsptok(NULL, &length);            /* eat :resno */
  719.     token = lsptok(NULL, &length);            /* get resno */
  720.  
  721.     local_node->resno = atoi(token);
  722.  
  723.     token = lsptok(NULL, &length);            /* eat :restype */
  724.     token = lsptok(NULL, &length);            /* get restype */
  725.  
  726.     local_node->restype = atol(token);
  727.  
  728.     token = lsptok(NULL, &length);            /* eat :rescomplex */
  729.     token = lsptok(NULL, &length);            /* get rescomplex */
  730.  
  731.     if (!strncmp(token, "true", 4))
  732.     {
  733.         local_node->rescomplex = true;
  734.     }
  735.     else
  736.     {
  737.         local_node->rescomplex = false;
  738.     }
  739.  
  740.     token = lsptok(NULL, &length);            /* eat :reslen */
  741.     token = lsptok(NULL, &length);            /* get reslen */
  742.  
  743.     local_node->reslen = atoi(token);
  744.  
  745.     token = lsptok(NULL, &length);            /* eat :resname */
  746.     token = lsptok(NULL, &length);            /* get the name */
  747.  
  748.     if (!strncmp(token, "\"null\"", 5))
  749.     {
  750.         local_node->resname = NULL;
  751.     }
  752.     else
  753.     {
  754.         /*
  755.          * Peel off ""'s, then make a true copy.
  756.          */
  757.  
  758.         token++;
  759.         token[length - 2] = '\0';
  760.  
  761.         local_node->resname = (Name) palloc(sizeof(char16));
  762.         strcpy(local_node->resname, token);
  763.         token[length - 2] = '\"';
  764.     }
  765.  
  766.     token = lsptok(NULL, &length);            /* eat :reskey */
  767.     token = lsptok(NULL, &length);            /* get reskey */
  768.  
  769.     local_node->reskey = atoi(token);
  770.  
  771.     token = lsptok(NULL, &length);            /* eat :reskeyop */
  772.  
  773.     token = lsptok(NULL, &length);            /* get reskeyop */
  774.  
  775.     local_node->reskeyop = (OperatorTupleForm) atol(token);
  776.  
  777.     token = lsptok(NULL, &length);            /* eat :resjunk */
  778.     token = lsptok(NULL, &length);            /* get resjunk */
  779.     local_node->resjunk = atoi(token);
  780.  
  781.     return(local_node);
  782. }
  783.  
  784. /* ----------------
  785.  *    _readExpr
  786.  *    
  787.  *  Expr is a subclass of Node
  788.  * ----------------
  789.  */
  790. Expr
  791. _readExpr()
  792. {
  793.     Expr local_node;
  794.  
  795.     local_node = RMakeExpr();
  796.  
  797.     return(local_node);
  798. }
  799.  
  800. /* ----------------
  801.  *    _readVar
  802.  *    
  803.  *  Var is a subclass of Expr
  804.  * ----------------
  805.  */
  806. Var
  807. _readVar()
  808. {
  809.     Var        local_node;
  810.     char        *token;
  811.     int length;
  812.  
  813.     local_node = RMakeVar();
  814.  
  815.     token = lsptok(NULL, &length);            /* eat :varno */
  816.     token = lsptok(NULL, &length);            /* get varno */
  817.     
  818.     local_node->varno = atoi(token);
  819.  
  820.     token = lsptok(NULL, &length);            /* eat :varattno */
  821.     token = lsptok(NULL, &length);            /* get varattno */
  822.     
  823.     local_node->varattno = atoi(token);
  824.  
  825.     token = lsptok(NULL, &length);            /* eat :vartype */
  826.     token = lsptok(NULL, &length);            /* get vartype */
  827.     
  828.     local_node->vartype = (ObjectId) atol(token);
  829.  
  830.     token = lsptok(NULL, &length);            /* eat :varid */
  831.     local_node->varid = lispRead(true);         /* now read it */
  832.  
  833.     return(local_node);
  834. }
  835.  
  836. /* ----------------
  837.  * _readArray
  838.  *
  839.  * Array is a subclass of Expr
  840.  * ----------------
  841.  */
  842.  
  843. Array
  844. _readArray()
  845.  
  846. {
  847.     Array        local_node;
  848.     char        *token;
  849.     int length;
  850.  
  851.     local_node = RMakeArray();
  852.  
  853.     token = lsptok(NULL, &length);            /* eat :arrayelemtype */
  854.     token = lsptok(NULL, &length);            /* get arrayelemtype */
  855.     
  856.     local_node->arrayelemtype = (ObjectId) atoi(token);
  857.  
  858.     token = lsptok(NULL, &length);            /* eat :arrayelemlength */
  859.     token = lsptok(NULL, &length);            /* get arrayelemlength */
  860.     
  861.     local_node->arrayelemlength = atoi(token);
  862.  
  863.     token = lsptok(NULL, &length);            /* eat :arrayelembyval */
  864.     token = lsptok(NULL, &length);            /* get arrayelembyval */
  865.     
  866.     local_node->arrayelembyval = (token[0] == 't') ? true : false;
  867.  
  868.     token = lsptok(NULL, &length);            /* eat :arraylow */
  869.     token = lsptok(NULL, &length);            /* get arraylow */
  870.  
  871.     local_node->arraylow = atoi(token);
  872.  
  873.     token = lsptok(NULL, &length);            /* eat :arrayhigh */
  874.     token = lsptok(NULL, &length);            /* get arrayhigh */
  875.  
  876.     local_node->arrayhigh = atoi(token);
  877.  
  878.     token = lsptok(NULL, &length);            /* eat :arraylen */
  879.     token = lsptok(NULL, &length);            /* get arraylen */
  880.  
  881.     local_node->arraylen = atoi(token);
  882.  
  883.     return(local_node);
  884. }
  885.  
  886. /* ----------------
  887.  * _readArrayRef
  888.  *
  889.  * ArrayRef is a subclass of Expr
  890.  * ----------------
  891.  */
  892.  
  893. ArrayRef
  894. _readArrayRef()
  895.  
  896. {
  897.     ArrayRef    local_node;
  898.     char        *token;
  899.     int        length;
  900.  
  901.     local_node = RMakeArrayRef();
  902.  
  903.     token = lsptok(NULL, &length);            /* eat :refelemtype */
  904.     token = lsptok(NULL, &length);            /* get refelemtype */
  905.     
  906.     local_node->refelemtype = (ObjectId) atoi(token);
  907.  
  908.     token = lsptok(NULL, &length);            /* eat :refattrlength */
  909.     token = lsptok(NULL, &length);            /* get refattrlength */
  910.     
  911.     local_node->refattrlength = atoi(token);
  912.  
  913.     token = lsptok(NULL, &length);            /* eat :refelemlength */
  914.     token = lsptok(NULL, &length);            /* get refelemlength */
  915.     
  916.     local_node->refelemlength = atoi(token);
  917.  
  918.     token = lsptok(NULL, &length);            /* eat :refelembyval */
  919.     token = lsptok(NULL, &length);            /* get refelembyval */
  920.     
  921.     local_node->refelembyval = (token[0] == 't') ? true : false;
  922.  
  923.     token = lsptok(NULL, &length);            /* eat :refindex */
  924.     local_node->refindexpr = (LispValue) lispRead(true);
  925.  
  926.     token = lsptok(NULL, &length);            /* eat :refexpr */
  927.     local_node->refexpr = (LispValue) lispRead(true);
  928.  
  929.     return(local_node);
  930. }
  931.  
  932. /* ----------------
  933.  *    _readConst
  934.  *    
  935.  *  Const is a subclass of Expr
  936.  * ----------------
  937.  */
  938. Const
  939. _readConst()
  940. {
  941.     Const    local_node;
  942.     char *token;
  943.     int length;
  944.  
  945.     local_node = RMakeConst();
  946.  
  947.     token = lsptok(NULL, &length);      /* get :consttype */
  948.     token = lsptok(NULL, &length);      /* now read it */
  949.  
  950.     local_node->consttype = atol(token);
  951.  
  952.  
  953.     token = lsptok(NULL, &length);      /* get :constlen */
  954.     token = lsptok(NULL, &length);      /* now read it */
  955.  
  956.     local_node->constlen = atoi(token);
  957.  
  958.     token = lsptok(NULL, &length);      /* get :constisnull */
  959.     token = lsptok(NULL, &length);      /* now read it */
  960.  
  961.     if (!strncmp(token, "true", 4))
  962.     {
  963.         local_node->constisnull = true;
  964.     }
  965.     else
  966.     {
  967.         local_node->constisnull = false;
  968.     }
  969.  
  970.  
  971.     token = lsptok(NULL, &length);      /* get :constvalue */
  972.  
  973.     if (local_node->constisnull) {
  974.         token = lsptok(NULL, &length);      /* skip "NIL" */
  975.     } else {
  976.         /*
  977.          * read the value
  978.          */
  979.         local_node->constvalue = readValue(local_node->consttype);
  980.     }
  981.  
  982.     token = lsptok(NULL, &length);      /* get :constbyval */
  983.     token = lsptok(NULL, &length);      /* now read it */
  984.  
  985.     if (!strncmp(token, "true", 4))
  986.     {
  987.         local_node->constbyval = true;
  988.     }
  989.     else
  990.     {
  991.         local_node->constbyval = false;
  992.     }
  993.     
  994.     return(local_node);
  995. }
  996.  
  997. /* ----------------
  998.  *    _readFunc
  999.  *    
  1000.  *  Func is a subclass of Expr
  1001.  * ----------------
  1002.  */
  1003. Func
  1004. _readFunc()
  1005. {
  1006.     Func    local_node;
  1007.     char *token;
  1008.     int length;
  1009.  
  1010.     local_node = RMakeFunc();
  1011.  
  1012.     token = lsptok(NULL, &length);      /* get :funcid */
  1013.     token = lsptok(NULL, &length);      /* now read it */
  1014.  
  1015.     local_node->funcid = atol(token);
  1016.  
  1017.     token = lsptok(NULL, &length);      /* get :functype */
  1018.     token = lsptok(NULL, &length);      /* now read it */
  1019.  
  1020.     local_node->functype = atol(token);
  1021.  
  1022.     token = lsptok(NULL, &length);      /* get :funcisindex */
  1023.     token = lsptok(NULL, &length);      /* now read it */
  1024.  
  1025.     if (!strncmp(token, "true", 4))
  1026.     {
  1027.         local_node->funcisindex = true;
  1028.     }
  1029.     else
  1030.     {
  1031.         local_node->funcisindex = false;
  1032.     }
  1033.     local_node->func_fcache = (FunctionCache *) NULL;
  1034.  
  1035.     token = lsptok(NULL, &length);            /* get :func_tlist */
  1036.     local_node->func_tlist = lispRead(true);  /* now read it */
  1037.  
  1038.     token = lsptok(NULL, &length);              /* get :func_planlist */
  1039.     local_node->func_planlist = lispRead(true); /* now read it */
  1040.     
  1041.     return(local_node);
  1042. }
  1043.  
  1044. /* ----------------
  1045.  *    _readOper
  1046.  *    
  1047.  *  Oper is a subclass of Expr
  1048.  * ----------------
  1049.  */
  1050. Oper
  1051. _readOper()
  1052. {
  1053.     Oper    local_node;
  1054.     char     *token;
  1055.     int length;
  1056.  
  1057.     local_node = RMakeOper();
  1058.  
  1059.     token = lsptok(NULL, &length);      /* get :opno */
  1060.     token = lsptok(NULL, &length);      /* now read it */
  1061.  
  1062.     local_node->opno = atol(token);
  1063.  
  1064.     token = lsptok(NULL, &length);      /* get :opid */
  1065.     token = lsptok(NULL, &length);      /* now read it */
  1066.     local_node->opid = atol(token);
  1067.  
  1068.     token = lsptok(NULL, &length);      /* get :oprelationlevel */
  1069.     token = lsptok(NULL, &length);      /* now read it */
  1070.  
  1071.     if (!strncmp(token, "non-nil", 7))
  1072.     {
  1073.         local_node->oprelationlevel = true;
  1074.     }
  1075.     else
  1076.     {
  1077.         local_node->oprelationlevel = false;
  1078.     }
  1079.  
  1080.     token = lsptok(NULL, &length);      /* get :opresulttype */
  1081.     token = lsptok(NULL, &length);      /* now read it */
  1082.  
  1083.     local_node->opresulttype = atol(token);
  1084.  
  1085.     /*
  1086.      * NOTE: Alternatively we can call 'replace_opid' 
  1087.      * which initializes both 'opid' and 'op_fcache'.
  1088.      */
  1089.     local_node->op_fcache = (FunctionCache *) NULL;
  1090.  
  1091.     return(local_node);
  1092. }
  1093.  
  1094. /* ----------------
  1095.  *    _readParam
  1096.  *    
  1097.  *  Param is a subclass of Expr
  1098.  * ----------------
  1099.  */
  1100. Param
  1101. _readParam()
  1102. {
  1103.     Param    local_node;
  1104.     char     *token;
  1105.     int length;
  1106.  
  1107.     local_node = RMakeParam();
  1108.  
  1109.     token = lsptok(NULL, &length);      /* get :paramkind */
  1110.     token = lsptok(NULL, &length);      /* now read it */
  1111.  
  1112.     local_node->paramkind = atoi(token);
  1113.  
  1114.     token = lsptok(NULL, &length);      /* get :paramid */
  1115.     token = lsptok(NULL, &length);      /* now read it */
  1116.  
  1117.     local_node->paramid = atol(token);
  1118.  
  1119.     token = lsptok(NULL, &length);      /* get :paramname */
  1120.     token = lsptok(NULL, &length);      /* now read it */
  1121.     token++;                /* skip the first `"' */
  1122.     token[length - 2] = '\0';        /* this is the 2nd `"' */
  1123.  
  1124.     local_node->paramname = (Name) palloc(sizeof(char16));
  1125.     strcpy(local_node->paramname, token);
  1126.     token[length - 2] = '\"';    /* restore the 2nd `"' */
  1127.  
  1128.     token = lsptok(NULL, &length);      /* get :paramtype */
  1129.     token = lsptok(NULL, &length);      /* now read it */
  1130.  
  1131.     local_node->paramtype = atol(token);
  1132.     token = lsptok(NULL, &length);             /* get :param_tlist */
  1133.     local_node->param_tlist = lispRead(true);  /* now read it */
  1134.     
  1135.     return(local_node);
  1136. }
  1137.  
  1138. /*
  1139.  *  Stuff from execnodes.h
  1140.  */
  1141.  
  1142. /* ----------------
  1143.  *    _readEState
  1144.  *    
  1145.  *  EState is a subclass of Node.
  1146.  * ----------------
  1147.  */
  1148. EState
  1149. _readEState()
  1150. {
  1151.     EState    local_node;
  1152.     char *token;
  1153.     int length;
  1154.  
  1155.     local_node = RMakeEState();
  1156.  
  1157.     token = lsptok(NULL, &length);      /* get :direction */
  1158.     token = lsptok(NULL, &length);      /* now read it */
  1159.  
  1160.     local_node->es_direction = atoi(token);
  1161.  
  1162.     token = lsptok(NULL, &length);      /* get :time */
  1163.     token = lsptok(NULL, &length);      /* now read it */
  1164.  
  1165.     local_node->es_time = (unsigned long) atoi(token);
  1166.  
  1167.     token = lsptok(NULL, &length);      /* get :owner */
  1168.     token = lsptok(NULL, &length);      /* now read it */
  1169.  
  1170.     local_node->es_owner = atol(token);
  1171.  
  1172.     token = lsptok(NULL, &length);      /* get :locks */
  1173.  
  1174.     local_node->es_locks = lispRead(true);   /* now read it */
  1175.  
  1176.     token = lsptok(NULL, &length);      /* get :subplan_info */
  1177.  
  1178.     local_node->es_subplan_info = lispRead(true); /* now read it */
  1179.  
  1180.     token = lsptok(NULL, &length);      /* get :error_message */
  1181.     token = lsptok(NULL, &length);      /* now read it */
  1182.     token++;
  1183.     token[length-2] = '\0';
  1184.  
  1185.     local_node->es_error_message = (Name) palloc(sizeof(char16));
  1186.     strcpy(local_node->es_error_message, token);
  1187.  
  1188.     token[length-2] = '\"';
  1189.  
  1190.     token = lsptok(NULL, &length);      /* get :range_table */
  1191.  
  1192.     local_node->es_locks = lispRead(true); /* now read it */
  1193.  
  1194.     token = lsptok(NULL, &length);      /* get :qualification_tuple */
  1195.     token = lsptok(NULL, &length);      /* get @ */
  1196.     token = lsptok(NULL, &length);      /* now read it */
  1197.  
  1198.     sscanf(token, "%x", &local_node->es_qualification_tuple);
  1199.  
  1200.     token = lsptok(NULL, &length);      /* get :qualification_tuple_id */
  1201.     token = lsptok(NULL, &length);      /* get @ */
  1202.     token = lsptok(NULL, &length);      /* now read it */
  1203.  
  1204.     sscanf(token, "%x", &local_node->es_qualification_tuple_id);
  1205.  
  1206.     token = lsptok(NULL, &length); /* get :relation_relation_descriptor */
  1207.     token = lsptok(NULL, &length);      /* get @ */
  1208.     token = lsptok(NULL, &length);      /* now read it */
  1209.  
  1210.     sscanf(token, "%x", &local_node->es_relation_relation_descriptor);
  1211.  
  1212.     token = lsptok(NULL, &length);      /* get :result_relation_info */
  1213.     token = lsptok(NULL, &length);      /* get @ */
  1214.     token = lsptok(NULL, &length);      /* now read it */
  1215.  
  1216.     sscanf(token, "%x", &local_node->es_result_relation_info);
  1217.     
  1218.     return(local_node);
  1219. }
  1220.  
  1221. /*
  1222.  *  Stuff from relation.h
  1223.  */
  1224.  
  1225. /* ----------------
  1226.  *    _readRel
  1227.  * ----------------
  1228.  */
  1229. Rel
  1230. _readRel()
  1231. {
  1232.     Rel    local_node;
  1233.     char     *token;
  1234.     int length;
  1235.  
  1236.     local_node = RMakeRel();
  1237.  
  1238.     token = lsptok(NULL, &length);      /* get :relids */
  1239.     local_node->relids = lispRead(true);/* now read it */
  1240.  
  1241.     token = lsptok(NULL, &length);      /* get :indexed */
  1242.     token = lsptok(NULL, &length);      /* now read it */
  1243.  
  1244.     if (!strncmp(token, "true", 4))
  1245.     {
  1246.         local_node->indexed = true;
  1247.     }
  1248.     else
  1249.     {
  1250.         local_node->indexed = false;
  1251.     }
  1252.  
  1253.     token = lsptok(NULL, &length);      /* get :pages */
  1254.     token = lsptok(NULL, &length);      /* now read it */
  1255.  
  1256.     local_node->pages = (unsigned int) atoi(token);
  1257.  
  1258.     token = lsptok(NULL, &length);      /* get :tuples */
  1259.     token = lsptok(NULL, &length);      /* now read it */
  1260.  
  1261.     local_node->tuples = (unsigned int) atoi(token);
  1262.  
  1263.     token = lsptok(NULL, &length);      /* get :size */
  1264.     token = lsptok(NULL, &length);      /* now read it */
  1265.  
  1266.     local_node->size = (unsigned int) atoi(token);
  1267.  
  1268.     token = lsptok(NULL, &length);      /* get :width */
  1269.     token = lsptok(NULL, &length);      /* now read it */
  1270.  
  1271.     local_node->width = (unsigned int) atoi(token);
  1272.  
  1273.     token = lsptok(NULL, &length);      /* get :targetlist */
  1274.     local_node->targetlist = lispRead(true); /* now read it */
  1275.  
  1276.     token = lsptok(NULL, &length);      /* get :pathlist */
  1277.     local_node->pathlist = lispRead(true); /* now read it */
  1278.  
  1279.     /*
  1280.      *  Not sure if these are nodes or not.  They're declared as
  1281.      *  struct Path *.  Since i don't know, i'll just print the
  1282.      *  addresses for now.  This can be changed later, if necessary.
  1283.      */
  1284.  
  1285.     token = lsptok(NULL, &length);      /* get :unorderpath */
  1286.     token = lsptok(NULL, &length);      /* get @ */
  1287.     token = lsptok(NULL, &length);      /* now read it */
  1288.  
  1289.     sscanf(token, "%x", &local_node->unorderedpath);
  1290.  
  1291.     token = lsptok(NULL, &length);      /* get :cheapestpath */
  1292.     token = lsptok(NULL, &length);      /* get @ */
  1293.     token = lsptok(NULL, &length);      /* now read it */
  1294.  
  1295.     sscanf(token, "%x", &local_node->cheapestpath);
  1296.  
  1297.     token = lsptok(NULL, &length);      /* get :classlist */
  1298.     local_node->classlist = lispRead(true); /* now read it */
  1299.  
  1300.     token = lsptok(NULL, &length);      /* get :indexkeys */
  1301.     local_node->indexkeys = lispRead(true);/* now read it */
  1302.  
  1303.     token = lsptok(NULL, &length);      /* get :ordering */
  1304.     local_node->ordering = lispRead(true); /* now read it */
  1305.  
  1306.     token = lsptok(NULL, &length);      /* get :clauseinfo */
  1307.     local_node->clauseinfo = lispRead(true); /* now read it */
  1308.  
  1309.     token = lsptok(NULL, &length);      /* get :joininfo */
  1310.     local_node->joininfo = lispRead(true); /* now read it */
  1311.  
  1312.     token = lsptok(NULL, &length);      /* get :innerjoin */
  1313.     local_node->innerjoin = lispRead(true); /* now read it */
  1314.     
  1315.     return(local_node);
  1316. }
  1317.  
  1318. /* ----------------
  1319.  *    _readSortKey
  1320.  *    
  1321.  *  SortKey is a subclass of Node.
  1322.  * ----------------
  1323.  */
  1324.  
  1325. SortKey
  1326. _readSortKey()
  1327. {
  1328.     SortKey        local_node;
  1329.     char        *token;
  1330.     int length;
  1331.  
  1332.     local_node = RMakeSortKey();
  1333.     token = lsptok(NULL, &length);      /* get :varkeys */
  1334.     local_node->varkeys = lispRead(true); /* now read it */
  1335.  
  1336.     token = lsptok(NULL, &length);      /* get :sortkeys */
  1337.     local_node->sortkeys = lispRead(true); /* now read it */
  1338.  
  1339.     token = lsptok(NULL, &length);      /* get :relid */
  1340.     local_node->relid = lispRead(true);      /* now read it */
  1341.  
  1342.     token = lsptok(NULL, &length);      /* get :sortorder */
  1343.     local_node->sortorder = lispRead(true);      /* now read it */
  1344.     
  1345.     return(local_node);
  1346. }
  1347.  
  1348. /* ----------------
  1349.  *    _readPath
  1350.  *    
  1351.  *  Path is a subclass of Node.
  1352.  * ----------------
  1353.  */
  1354. Path
  1355. _readPath()
  1356. {
  1357.     Path    local_node;
  1358.     char     *token;
  1359.     int length;
  1360.  
  1361.     local_node = RMakePath();
  1362.  
  1363.     token = lsptok(NULL, &length);      /* get :pathtype */
  1364.     token = lsptok(NULL, &length);      /* now read it */
  1365.  
  1366.     local_node->pathtype = atol(token);
  1367.  
  1368.     token = lsptok(NULL, &length);      /* get :cost */
  1369.     token = lsptok(NULL, &length);      /* now read it */
  1370.  
  1371.     local_node->path_cost = (Cost) atof(token);
  1372.  
  1373.     token = lsptok(NULL, &length);      /* get :p_ordering */
  1374.     local_node->p_ordering = lispRead(true);      /* now read it */
  1375.  
  1376.     token = lsptok(NULL, &length);      /* get :keys */
  1377.     local_node->keys = lispRead(true);       /* now read it */
  1378.  
  1379.     token = lsptok(NULL, &length);      /* get :pathsortkey */
  1380.     local_node->pathsortkey = (SortKey) lispRead(true);
  1381.  
  1382.     return(local_node);
  1383. }
  1384.  
  1385. /* ----------------
  1386.  *    _readIndexPath
  1387.  *    
  1388.  *  IndexPath is a subclass of Path.
  1389.  * ----------------
  1390.  */
  1391. IndexPath
  1392. _readIndexPath()
  1393. {
  1394.     IndexPath    local_node;
  1395.     char        *token;
  1396.     int length;
  1397.  
  1398.     local_node = RMakeIndexPath();
  1399.  
  1400.     token = lsptok(NULL, &length);      /* get :pathtype */
  1401.     token = lsptok(NULL, &length);      /* now read it */
  1402.  
  1403.     local_node->pathtype = atol(token);
  1404.  
  1405.     token = lsptok(NULL, &length);      /* get :cost */
  1406.     token = lsptok(NULL, &length);      /* now read it */
  1407.  
  1408.     local_node->path_cost = (Cost) atof(token);
  1409.  
  1410.     token = lsptok(NULL, &length);      /* get :p_ordering */
  1411.     local_node->p_ordering = lispRead(true);      /* now read it */
  1412.  
  1413.     token = lsptok(NULL, &length);      /* get :keys */
  1414.     local_node->keys = lispRead(true);       /* now read it */
  1415.  
  1416.     token = lsptok(NULL, &length);      /* get :pathsortkey */
  1417.     local_node->pathsortkey = (SortKey) lispRead(true);
  1418.  
  1419.     token = lsptok(NULL, &length);      /* get :indexid */
  1420.     local_node->indexid = lispRead(true);
  1421.  
  1422.     token = lsptok(NULL, &length);      /* get :indexqual */
  1423.     local_node->indexqual = lispRead(true);      /* now read it */
  1424.  
  1425.     return(local_node);
  1426. }
  1427.  
  1428. /* ----------------
  1429.  *    _readJoinPath
  1430.  *    
  1431.  *  JoinPath is a subclass of Path
  1432.  * ----------------
  1433.  */
  1434. JoinPath
  1435. _readJoinPath()
  1436. {
  1437.     JoinPath    local_node;
  1438.     char        *token;
  1439.     int length;
  1440.  
  1441.  
  1442.     local_node = RMakeJoinPath();
  1443.  
  1444.     token = lsptok(NULL, &length);      /* get :pathtype */
  1445.     token = lsptok(NULL, &length);      /* now read it */
  1446.  
  1447.     local_node->pathtype = atol(token);
  1448.  
  1449.     token = lsptok(NULL, &length);      /* get :cost */
  1450.     token = lsptok(NULL, &length);      /* now read it */
  1451.  
  1452.     local_node->path_cost = (Cost) atof(token);
  1453.  
  1454.     token = lsptok(NULL, &length);      /* get :p_ordering */
  1455.     local_node->p_ordering = lispRead(true);           /* now read it */
  1456.  
  1457.     token = lsptok(NULL, &length);      /* get :keys */
  1458.     local_node->keys = lispRead(true);            /* now read it */
  1459.  
  1460.     token = lsptok(NULL, &length);      /* get :pathsortkey */
  1461.     local_node->pathsortkey = (SortKey) lispRead(true);
  1462.  
  1463.     token = lsptok(NULL, &length);      /* get :pathclauseinfo */
  1464.     local_node->pathclauseinfo = lispRead(true);         /* now read it */
  1465.  
  1466.     /*
  1467.      *  Not sure if these are nodes; they're declared as "struct path *".
  1468.      *  For now, i'll just print the addresses.
  1469.      *
  1470.      * GJK:  Since I am parsing this stuff, I'll just ignore the addresses,
  1471.      * and initialize these pointers to NULL.
  1472.      */
  1473.  
  1474.     token = lsptok(NULL, &length);      /* get :outerjoinpath */
  1475.     token = lsptok(NULL, &length);      /* get @ */
  1476.     token = lsptok(NULL, &length);      /* now read it */
  1477.  
  1478.     local_node->outerjoinpath = NULL;
  1479.  
  1480.     token = lsptok(NULL, &length);      /* get :innerjoinpath */
  1481.     token = lsptok(NULL, &length);      /* get @ */
  1482.     token = lsptok(NULL, &length);      /* now read it */
  1483.  
  1484.     local_node->innerjoinpath = NULL;
  1485.  
  1486.     token = lsptok(NULL, &length);      /* get :outerjoincost */
  1487.     token = lsptok(NULL, &length);      /* now read it */
  1488.  
  1489.     local_node->outerjoincost = (Cost) atof(token);
  1490.  
  1491.     token = lsptok(NULL, &length);      /* get :joinid */
  1492.     local_node->joinid = lispRead(true);          /* now read it */
  1493.  
  1494.     return(local_node);
  1495. }
  1496.  
  1497. /* ----------------
  1498.  *    _readMergePath
  1499.  *    
  1500.  *  MergePath is a subclass of JoinPath.
  1501.  * ----------------
  1502.  */
  1503.  
  1504. MergePath
  1505. _readMergePath()
  1506. {
  1507.     MergePath    local_node;
  1508.     char         *token;
  1509.     int length;
  1510.  
  1511.     local_node = RMakeMergePath();
  1512.  
  1513.     token = lsptok(NULL, &length);      /* get :pathtype */
  1514.     token = lsptok(NULL, &length);      /* now read it */
  1515.  
  1516.     local_node->pathtype = atol(token);
  1517.  
  1518.     token = lsptok(NULL, &length);      /* get :cost */
  1519.     token = lsptok(NULL, &length);      /* now read it */
  1520.  
  1521.     local_node->path_cost = (Cost) atof(token);
  1522.  
  1523.     token = lsptok(NULL, &length);      /* get :p_ordering */
  1524.     local_node->p_ordering = lispRead(true);           /* now read it */
  1525.  
  1526.     token = lsptok(NULL, &length);      /* get :keys */
  1527.     local_node->keys = lispRead(true);            /* now read it */
  1528.  
  1529.     token = lsptok(NULL, &length);      /* get :pathsortkey */
  1530.     local_node->pathsortkey = (SortKey) lispRead(true);
  1531.  
  1532.     token = lsptok(NULL, &length);      /* get :pathclauseinfo */
  1533.     local_node->pathclauseinfo = lispRead(true);        /* now read it */
  1534.  
  1535.     /*
  1536.      *  Not sure if these are nodes; they're declared as "struct path *".
  1537.      *  For now, i'll just print the addresses.
  1538.      *
  1539.      * GJK:  Since I am parsing this stuff, I'll just ignore the addresses,
  1540.      * and initialize these pointers to NULL.
  1541.      */
  1542.  
  1543.     token = lsptok(NULL, &length);      /* get :outerjoinpath */
  1544.     token = lsptok(NULL, &length);      /* get @ */
  1545.     token = lsptok(NULL, &length);      /* now read it */
  1546.  
  1547.     local_node->outerjoinpath = NULL;
  1548.  
  1549.     token = lsptok(NULL, &length);      /* get :innerjoinpath */
  1550.     token = lsptok(NULL, &length);      /* get @ */
  1551.     token = lsptok(NULL, &length);      /* now read it */
  1552.  
  1553.     local_node->innerjoinpath = NULL;
  1554.  
  1555.     token = lsptok(NULL, &length);      /* get :outerjoincost */
  1556.     token = lsptok(NULL, &length);      /* now read it */
  1557.  
  1558.     local_node->outerjoincost = (Cost) atof(token);
  1559.  
  1560.     token = lsptok(NULL, &length);      /* get :joinid */
  1561.     local_node->joinid = lispRead(true);          /* now read it */
  1562.  
  1563.     token = lsptok(NULL, &length);      /* get :path_mergeclauses */
  1564.     local_node->path_mergeclauses = lispRead(true);      /* now read it */
  1565.  
  1566.     token = lsptok(NULL, &length);      /* get :outersortkeys */
  1567.     local_node->outersortkeys = lispRead(true);           /* now read it */
  1568.  
  1569.     token = lsptok(NULL, &length);      /* get :innersortkeys */
  1570.     local_node->innersortkeys = lispRead(true);           /* now read it */
  1571.  
  1572.     return(local_node);
  1573. }
  1574.  
  1575. /* ----------------
  1576.  *    _readHashPath
  1577.  *    
  1578.  *  HashPath is a subclass of JoinPath.
  1579.  * ----------------
  1580.  */
  1581. HashPath
  1582. _readHashPath()
  1583. {
  1584.     HashPath    local_node;
  1585.     char         *token;
  1586.     int length;
  1587.  
  1588.     local_node = RMakeHashPath();
  1589.  
  1590.     token = lsptok(NULL, &length);      /* get :pathtype */
  1591.     token = lsptok(NULL, &length);      /* now read it */
  1592.  
  1593.     local_node->pathtype = atol(token);
  1594.  
  1595.     token = lsptok(NULL, &length);      /* get :cost */
  1596.     token = lsptok(NULL, &length);      /* now read it */
  1597.  
  1598.     local_node->path_cost = (Cost) atof(token);
  1599.  
  1600.     token = lsptok(NULL, &length);      /* get :p_ordering */
  1601.     local_node->p_ordering = lispRead(true); /* now read it */
  1602.  
  1603.     token = lsptok(NULL, &length);      /* get :keys */
  1604.     local_node->keys = lispRead(true);       /* now read it */
  1605.  
  1606.     token = lsptok(NULL, &length);      /* get :pathsortkey */
  1607.     local_node->pathsortkey = (SortKey) lispRead(true);
  1608.  
  1609.     token = lsptok(NULL, &length);      /* get :pathclauseinfo */
  1610.     local_node->pathclauseinfo = lispRead(true); /* now read it */
  1611.  
  1612.     /*
  1613.      *  Not sure if these are nodes; they're declared as "struct path *".
  1614.      *  For now, i'll just print the addresses.
  1615.      *
  1616.      * GJK:  Since I am parsing this stuff, I'll just ignore the addresses,
  1617.      * and initialize these pointers to NULL.
  1618.      */
  1619.  
  1620.     token = lsptok(NULL, &length);      /* get :outerjoinpath */
  1621.     token = lsptok(NULL, &length);      /* get @ */
  1622.     token = lsptok(NULL, &length);      /* now read it */
  1623.  
  1624.     local_node->outerjoinpath = NULL;
  1625.  
  1626.     token = lsptok(NULL, &length);      /* get :innerjoinpath */
  1627.     token = lsptok(NULL, &length);      /* get @ */
  1628.     token = lsptok(NULL, &length);      /* now read it */
  1629.  
  1630.     local_node->innerjoinpath = NULL;
  1631.  
  1632.     token = lsptok(NULL, &length);      /* get :outerjoincost */
  1633.     token = lsptok(NULL, &length);      /* now read it */
  1634.  
  1635.     local_node->outerjoincost = (Cost) atof(token);
  1636.  
  1637.     token = lsptok(NULL, &length);      /* get :joinid */
  1638.     local_node->joinid = lispRead(true);     /* now read it */
  1639.  
  1640.     token = lsptok(NULL, &length);      /* get :path_hashclauses */
  1641.     local_node->path_hashclauses = lispRead(true); /* now read it */
  1642.  
  1643.     token = lsptok(NULL, &length);      /* get :outerhashkeys */
  1644.     local_node->outerhashkeys = lispRead(true); /* now read it */
  1645.  
  1646.     token = lsptok(NULL, &length);      /* get :innerhashkeys */
  1647.     local_node->innerhashkeys = lispRead(true); /* now read it */
  1648.  
  1649.     return(local_node);
  1650. }
  1651.  
  1652. /* ----------------
  1653.  *    _readOrderKey
  1654.  *    
  1655.  *  OrderKey is a subclass of Node.
  1656.  * ----------------
  1657.  */
  1658. OrderKey
  1659. _readOrderKey()
  1660. {
  1661.     OrderKey    local_node;
  1662.     char        *token;
  1663.     int length;
  1664.  
  1665.     local_node = RMakeOrderKey();
  1666.  
  1667.     token = lsptok(NULL, &length);      /* get :attribute_number */
  1668.     token = lsptok(NULL, &length);      /* now read it */
  1669.  
  1670.     local_node->attribute_number = atoi(token);
  1671.     
  1672.     token = lsptok(NULL, &length);      /* get :array_index */
  1673.     token = lsptok(NULL, &length);      /* now read it */
  1674.  
  1675.     local_node->array_index = atoi(token);
  1676.  
  1677.     return(local_node);
  1678. }
  1679.  
  1680. /* ----------------
  1681.  *    _readJoinKey
  1682.  *    
  1683.  *  JoinKey is a subclass of Node.
  1684.  * ----------------
  1685.  */
  1686.  
  1687. JoinKey
  1688. _readJoinKey()
  1689. {
  1690.     JoinKey        local_node;
  1691.     char        *token;
  1692.     int length;
  1693.  
  1694.     local_node = RMakeJoinKey();
  1695.  
  1696.     token = lsptok(NULL, &length);      /* get :outer */
  1697.     local_node->outer = lispRead(true);      /* now read it */
  1698.  
  1699.     token = lsptok(NULL, &length);      /* get :inner */
  1700.     local_node->inner = lispRead(true);      /* now read it */
  1701.     
  1702.     return(local_node);
  1703. }
  1704.  
  1705. /* ----------------
  1706.  *    _readMergeOrder
  1707.  *    
  1708.  *  MergeOrder is a subclass of Node.
  1709.  * ----------------
  1710.  */
  1711. MergeOrder
  1712. _readMergeOrder()
  1713. {
  1714.     MergeOrder    local_node;
  1715.     char        *token;
  1716.     int length;
  1717.  
  1718.     local_node = RMakeMergeOrder();
  1719.     token = lsptok(NULL, &length);      /* get :join_operator */
  1720.     token = lsptok(NULL, &length);      /* now read it */
  1721.  
  1722.     local_node->join_operator = atol(token);
  1723.  
  1724.     token = lsptok(NULL, &length);      /* get :left_operator */
  1725.     token = lsptok(NULL, &length);      /* now read it */
  1726.  
  1727.     local_node->left_operator = atol(token);
  1728.  
  1729.     token = lsptok(NULL, &length);      /* get :right_operator */
  1730.     token = lsptok(NULL, &length);      /* now read it */
  1731.  
  1732.     local_node->right_operator = atol(token);
  1733.  
  1734.     token = lsptok(NULL, &length);      /* get :left_type */
  1735.     token = lsptok(NULL, &length);      /* now read it */
  1736.  
  1737.     local_node->left_type = atol(token);
  1738.  
  1739.     token = lsptok(NULL, &length);      /* get :right_type */
  1740.     token = lsptok(NULL, &length);      /* now read it */
  1741.  
  1742.     local_node->right_type = atol(token);
  1743.  
  1744.     return(local_node);
  1745. }
  1746.  
  1747. /* ----------------
  1748.  *    _readCInfo
  1749.  *    
  1750.  *  CInfo is a subclass of Node.
  1751.  * ----------------
  1752.  */
  1753. CInfo
  1754. _readCInfo()
  1755. {
  1756.     CInfo    local_node;
  1757.     char     *token;
  1758.     int length;
  1759.  
  1760.     local_node = RMakeCInfo();
  1761.  
  1762.     token = lsptok(NULL, &length);      /* get :clause */
  1763.     local_node->clause = (LispValue) lispRead(true); /* now read it */
  1764.  
  1765.     token = lsptok(NULL, &length);      /* get :selectivity */
  1766.     token = lsptok(NULL, &length);      /* now read it */
  1767.  
  1768.     local_node->selectivity = atof(token);
  1769.  
  1770.     token = lsptok(NULL, &length);      /* get :notclause */
  1771.     token = lsptok(NULL, &length);      /* now read it */
  1772.  
  1773.     if (!strncmp(token, "true", 4))
  1774.     {
  1775.         local_node->notclause = true;
  1776.     }
  1777.     else
  1778.     {
  1779.         local_node->notclause = false;
  1780.     }
  1781.  
  1782.     token = lsptok(NULL, &length);      /* get :indexids */
  1783.     local_node->indexids = lispRead(true);   /* now read it */
  1784.  
  1785.     token = lsptok(NULL, &length);      /* get :mergesortorder */
  1786.     local_node->mergesortorder = (MergeOrder) lispRead(true);
  1787.  
  1788.     token = lsptok(NULL, &length);      /* get :hashjoinoperator */
  1789.     token = lsptok(NULL, &length);      /* now read it */
  1790.  
  1791.     local_node->hashjoinoperator = atol(token);
  1792.  
  1793.     return(local_node);
  1794. }
  1795.  
  1796. /* ----------------
  1797.  *    _readJoinMethod
  1798.  *    
  1799.  *  JoinMethod is a subclass of Node.
  1800.  * ----------------
  1801.  */
  1802. JoinMethod
  1803. _readJoinMethod()
  1804. {
  1805.          JoinMethod     local_node;
  1806.     char        *token;
  1807.     int length;
  1808.  
  1809.     local_node = RMakeJoinMethod();
  1810.  
  1811.     token = lsptok(NULL, &length);      /* get :jmkeys */
  1812.     local_node->jmkeys = lispRead(true);/* now read it */
  1813.  
  1814.     token = lsptok(NULL, &length);      /* get :clauses */
  1815.     local_node->clauses = lispRead(true); /* now read it */
  1816.  
  1817.     return(local_node);
  1818. }
  1819.  
  1820. /* ----------------
  1821.  *    _readHInfo
  1822.  *    
  1823.  * HInfo is a subclass of JoinMethod.
  1824.  * ----------------
  1825.  */
  1826. HInfo
  1827. _readHInfo()
  1828. {
  1829.     HInfo     local_node;
  1830.     char     *token;
  1831.     int length;
  1832.  
  1833.     local_node = RMakeHInfo();
  1834.  
  1835.     token = lsptok(NULL, &length);      /* get :hashop */
  1836.     token = lsptok(NULL, &length);      /* now read it */
  1837.     
  1838.     local_node->hashop = atoi(token);
  1839.  
  1840.     token = lsptok(NULL, &length);      /* get :jmkeys */
  1841.     local_node->jmkeys = lispRead(true); /* now read it */
  1842.  
  1843.     token = lsptok(NULL, &length);      /* get :clauses */
  1844.     local_node->clauses = lispRead(true);           /* now read it */
  1845.  
  1846.     return(local_node);
  1847. }
  1848.  
  1849. /* ----------------
  1850.  *    _readJInfo()
  1851.  *    
  1852.  *  JInfo is a subclass of Node.
  1853.  * ----------------
  1854.  */
  1855. JInfo
  1856. _readJInfo()
  1857. {
  1858.     JInfo    local_node;
  1859.     char    *token;
  1860.     int length;
  1861.  
  1862.     local_node = RMakeJInfo();
  1863.  
  1864.     token = lsptok(NULL, &length);      /* get :otherrels */
  1865.     local_node->otherrels = lispRead(true); /* now read it */
  1866.  
  1867.     token = lsptok(NULL, &length);      /* get :jinfoclauseinfo */
  1868.     local_node->jinfoclauseinfo = lispRead(true); /* now read it */
  1869.  
  1870.     token = lsptok(NULL, &length);      /* get :mergesortable */
  1871.  
  1872.     if (!strncmp(token, "true", 4))
  1873.     {
  1874.         local_node->mergesortable = true;
  1875.     }
  1876.     else
  1877.     {
  1878.         local_node->mergesortable = false;
  1879.     }
  1880.  
  1881.     token = lsptok(NULL, &length);      /* get :hashjoinable */
  1882.  
  1883.     if (!strncmp(token, "true", 4))
  1884.     {
  1885.         local_node->hashjoinable = true;
  1886.     }
  1887.     else
  1888.     {
  1889.         local_node->hashjoinable = false;
  1890.     }
  1891.  
  1892.     return(local_node);
  1893. }
  1894.  
  1895.  
  1896. /* ----------------
  1897.  *    parsePlanString
  1898.  *
  1899.  * Given a character string containing a plan, parsePlanString sets up the
  1900.  * plan structure representing that plan.
  1901.  *
  1902.  * The string passed to parsePlanString must be null-terminated.
  1903.  * ----------------
  1904.  */
  1905. LispValue
  1906. parsePlanString()
  1907. {
  1908.     char *token;
  1909.     int length;
  1910.     LispValue return_value;
  1911.  
  1912.     token = lsptok(NULL, &length);
  1913.  
  1914.     if (!strncmp(token, "plan", 4))
  1915.     {
  1916.         return_value = (LispValue) _readPlan();
  1917.         return_value->type = T_Plan;
  1918.     }
  1919.     else if (!strncmp(token, "result", 6))
  1920.     {
  1921.         return_value = (LispValue) _readResult();
  1922.         return_value->type = T_Result;
  1923.     }
  1924.     else if (!strncmp(token, "existential", 11))
  1925.     {
  1926.         return_value = (LispValue) _readExistential();
  1927.         return_value->type = T_Existential;
  1928.     }
  1929.     else if (!strncmp(token, "append", 6))
  1930.     {
  1931.         return_value = (LispValue) _readAppend();
  1932.         return_value->type = T_Append;
  1933.     }
  1934.     else if (!strncmp(token, "joinruleinfo", 12))
  1935.     {
  1936.         /*
  1937.          * NOTE: 'joinruleinfo' must be checked BEFORE
  1938.          * 'join', because both `strncmp' test will
  1939.          * succeeed !
  1940.          */
  1941.         return_value = (LispValue) _readJoinRuleInfo();
  1942.         return_value->type = T_JoinRuleInfo;
  1943.     }
  1944.     else if (!strncmp(token, "join", 4))
  1945.     {
  1946.         return_value = (LispValue) _readJoin();
  1947.         return_value->type = T_Join;
  1948.     }
  1949.     else if (!strncmp(token, "nestloop", 8))
  1950.     {
  1951.         return_value = (LispValue) _readNestLoop();
  1952.         return_value->type = T_NestLoop;
  1953.     }
  1954.     else if (!strncmp(token, "mergejoin", 9))
  1955.     {
  1956.         return_value = (LispValue) _readMergeJoin();
  1957.         return_value->type = T_MergeJoin;
  1958.     }
  1959.     else if (!strncmp(token, "hashjoin", 8))
  1960.     {
  1961.         return_value = (LispValue) _readHashJoin();
  1962.         return_value->type = T_HashJoin;
  1963.     }
  1964.     else if (!strncmp(token, "scan", 4))
  1965.     {
  1966.         return_value = (LispValue) _readScan();
  1967.         return_value->type = T_Scan;
  1968.     }
  1969.     else if (!strncmp(token, "seqscan", 7))
  1970.     {
  1971.         return_value = (LispValue) _readSeqScan();
  1972.         return_value->type = T_SeqScan;
  1973.     }
  1974.     else if (!strncmp(token, "indexscan", 9))
  1975.     {
  1976.         return_value = (LispValue) _readIndexScan();
  1977.         return_value->type = T_IndexScan;
  1978.     }
  1979.     else if (!strncmp(token, "temp", 4))
  1980.     {
  1981.         return_value = (LispValue) _readTemp();
  1982.         return_value->type = T_Temp;
  1983.     }
  1984.     else if (!strncmp(token, "sort", 4))
  1985.     {
  1986.         return_value = (LispValue) _readSort();
  1987.         return_value->type = T_Sort;
  1988.     }
  1989.     else if (!strncmp(token, "hash", 4))
  1990.     {
  1991.         return_value = (LispValue) _readHash();
  1992.         return_value->type = T_Hash;
  1993.     }
  1994.     else if (!strncmp(token, "resdom", 6))
  1995.     {
  1996.         return_value = (LispValue) _readResdom();
  1997.         return_value->type = T_Resdom;
  1998.     }
  1999.     else if (!strncmp(token, "expr", 4))
  2000.     {
  2001.         return_value = (LispValue) _readExpr();
  2002.         return_value->type = T_Expr;
  2003.     }
  2004.     else if (!strncmp(token, "var", 3))
  2005.     {
  2006.         return_value = (LispValue) _readVar();
  2007.         return_value->type = T_Var;
  2008.     }
  2009.     else if (!strncmp(token, "const", 5))
  2010.     {
  2011.         return_value = (LispValue) _readConst();
  2012.         return_value->type = T_Const;
  2013.     }
  2014.     else if (!strncmp(token, "func", 4))
  2015.     {
  2016.         return_value = (LispValue) _readFunc();
  2017.         return_value->type = T_Func;
  2018.     }
  2019.     else if (!strncmp(token, "oper", 4))
  2020.     {
  2021.         return_value = (LispValue) _readOper();
  2022.         return_value->type = T_Oper;
  2023.     }
  2024.     else if (!strncmp(token, "param", 5))
  2025.     {
  2026.         return_value = (LispValue) _readParam();
  2027.         return_value->type = T_Param;
  2028.     }
  2029.     else if (!strncmp(token, "estate", 6))
  2030.     {
  2031.         return_value = (LispValue) _readEState();
  2032.         return_value->type = T_EState;
  2033.     }
  2034.     else if (!strncmp(token, "rel", 3))
  2035.     {
  2036.         return_value = (LispValue) _readRel();
  2037.         return_value->type = T_Rel;
  2038.     }
  2039.     else if (!strncmp(token, "sortkey", 7))
  2040.     {
  2041.         return_value = (LispValue) _readSortKey();
  2042.         return_value->type = T_SortKey;
  2043.     }
  2044.     else if (!strncmp(token, "path", 4))
  2045.     {
  2046.         return_value = (LispValue) _readPath();
  2047.         return_value->type = T_Path;
  2048.     }
  2049.     else if (!strncmp(token, "indexpath", 9))
  2050.     {
  2051.         return_value = (LispValue) _readIndexPath();
  2052.         return_value->type = T_IndexPath;
  2053.     }
  2054.     else if (!strncmp(token, "joinpath", 8))
  2055.     {
  2056.         return_value = (LispValue) _readJoinPath();
  2057.         return_value->type = T_JoinPath;
  2058.     }
  2059.     else if (!strncmp(token, "mergepath", 9))
  2060.     {
  2061.         return_value = (LispValue) _readMergePath();
  2062.         return_value->type = T_MergePath;
  2063.     }
  2064.     else if (!strncmp(token, "hashpath", 8))
  2065.     {
  2066.         return_value = (LispValue) _readHashPath();
  2067.         return_value->type = T_HashPath;
  2068.     }
  2069.     else if (!strncmp(token, "orderkey", 8))
  2070.     {
  2071.         return_value = (LispValue) _readOrderKey();
  2072.         return_value->type = T_OrderKey;
  2073.     }
  2074.     else if (!strncmp(token, "joinkey", 7))
  2075.     {
  2076.         return_value = (LispValue) _readJoinKey();
  2077.         return_value->type = T_JoinKey;
  2078.     }
  2079.     else if (!strncmp(token, "mergeorder", 10))
  2080.     {
  2081.         return_value = (LispValue) _readMergeOrder();
  2082.         return_value->type = T_MergeOrder;
  2083.     }
  2084.     else if (!strncmp(token, "cinfo", 5))
  2085.     {
  2086.         return_value = (LispValue) _readCInfo();
  2087.         return_value->type = T_CInfo;
  2088.     }
  2089.     else if (!strncmp(token, "joinmethod", 10))
  2090.     {
  2091.         return_value = (LispValue) _readJoinMethod();
  2092.         return_value->type = T_JoinMethod;
  2093.     }
  2094.     else if (!strncmp(token, "jinfo", 5))
  2095.     {
  2096.         return_value = (LispValue) _readJInfo();
  2097.         return_value->type = T_JInfo;
  2098.     }
  2099.     else if (!strncmp(token, "array", 5))
  2100.     {
  2101.         return_value = (LispValue) _readArray();
  2102.         return_value->type = T_Array;
  2103.     }
  2104.     else
  2105.     {
  2106.         fprintf(stderr, "badly formatted planstring\n");
  2107.         return_value = (LispValue) NULL;
  2108.     }
  2109.     return(return_value);
  2110. }
  2111. /*------------------------------------------------------------*/
  2112.  
  2113. /* ----------------
  2114.  *    readValue
  2115.  *
  2116.  * given a string representation of the value of the given type,
  2117.  * create the appropriate Datum
  2118.  * ----------------
  2119.  */
  2120. Datum
  2121. readValue(type)
  2122.     ObjectId type;
  2123. {
  2124.     int     length;
  2125.     int     tokenLength;
  2126.     char     *token;
  2127.     Boolean    byValue;
  2128.     Datum     res;
  2129.     char     *s;
  2130.     int     i;
  2131.  
  2132.     byValue    = get_typbyval(type);
  2133.  
  2134.     /*
  2135.      * read the actual length of the value
  2136.      */
  2137.     token = lsptok(NULL, &tokenLength);
  2138.     length = atoi(token);
  2139.     token = lsptok(NULL, &tokenLength);    /* skip the '{' */
  2140.  
  2141.     if (byValue) {
  2142.     if (length > sizeof(Datum)) {
  2143.         elog(WARN, "readValue: byval & length = %d", length);
  2144.     }
  2145.     s = (char *) (&res);
  2146.     for (i=0; i<sizeof(Datum); i++) {
  2147.         token = lsptok(NULL, &tokenLength);
  2148.         s[i] = (char) atoi(token);
  2149.     }
  2150.     } else if (length <= 0) {
  2151.     s = NULL;
  2152.     } else if (length >= 1) {
  2153.     s = (char*)palloc(length);
  2154.     Assert( s!=NULL );
  2155.     for (i=0; i<length; i++) {
  2156.         token = lsptok(NULL, &tokenLength);
  2157.         s[i] = (char) atoi(token);
  2158.     }
  2159.     res = PointerGetDatum(s);
  2160.     }
  2161.  
  2162.     token = lsptok(NULL, &tokenLength);    /* skip the '}' */
  2163.     if (token[0] != '}') {
  2164.     elog(WARN, "readValue: '}' expected, length =%d", length);
  2165.     }
  2166.  
  2167.     return(res);
  2168. }
  2169.